home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-04-17 | 16.5 KB | 452 lines | [TEXT/MPS ] |
- TITLE 'Sample - A small sample application using Structured Macros'
-
- * File Sample.a using structured program macros
- * Copyright Apple Computer, Inc. 1985, 1986, 1987, 1988, 1989, 1990
- * All rights reserved.
-
- * Sample -- A small sample application written in MPW Assembler. It displays
- * single, fixed-size window in which the user can enter and edit text.
-
- * This is a translation of the Sample.a program in the Inside Macintosh
- * documentaion. Some changes were made to illustrate some of the features of
- * the MPW Assembler, but most comments and the order of the code is the same as
- * the Pascal example.
-
- * Note, this code assumes that the DEGUG switch available to the structured
- * macros is OFF (the preset case), since DoCommand pops its return and
- * parameter directly off the stack and doesn't know that with DEBUG set a
- * LINK on A6 is generated!
-
- * The PRINT directive turns off listing (if a listing is being generated using
- * -l command line option) of the standard include files. The INCLUDEs bring in
- * the equate and trap definitions needed by Sample. We could use the LOAD/DUMP
- * facilities on these includes if we intended to assemble this program over and
- * over again, but that would confuse the example here.
-
- PRINT OFF
- INCLUDE 'Traps.a'
- INCLUDE 'ToolEqu.a'
- INCLUDE 'QuickEqu.a'
- INCLUDE 'SysEqu.a'
- LOAD 'ProgStrucMacs.d'
- LOAD 'FlowCtlMacs.d'
- PRINT ON,NOGEN
-
-
- TITLE 'Global Declarations for Sample'
-
- *************
- * Constants *
- *************
-
- appleID EQU 128 ; Resource IDs/menu IDs for Apple,
- fileID EQU 129 ; File, and Edit menus
- editID EQU 130
-
- menuCount EQU 3 ; Total number of menus
-
- windowID EQU 128 ; Resource ID for application'w window
-
- undoCommand EQU 1 ; Menu item numbers identifying
- cutCommand EQU 3 ; commands in Edit menu
- copyCommand EQU 4
- pasteCommand EQU 5
- clearCommand EQU 6
-
- aboutMeDLOG EQU 128 ; Resource ID for the "about" dialog
-
- authorItem EQU 2 ; "About sample" dialog item numbers
- languageItem EQU 3
-
-
- *********
- * Types *
- *********
-
- * To illustrate how the template type feature works the following templates are
- * declared and used instead of the simple offsets defined in the equate files.
- * By using these, the Assember source appromixates very closely the Pascal
- * source for referencing the corresponding information. Perhaps someday we will
- * have a set of "equate" files that define types just like Pascal USES units do!
-
- Point RECORD 0 ; Point = RECORD CASE INTEGER OF
- v DS.W 1 ; 1: (v: INTEGER;
- h DS.W 1 ; h: INTEGER);
- ORG v ; 2: (vh: ARRAY[1..2] OF INTEGER)
- vh DS.L 1
- ENDR ; END;
-
- Rect RECORD 0 ; Rect = RECORD CASE INTEGER OF
- top DS.W 1 ; 1: (top: INTEGER;
- left DS.W 1 ; left: INTEGER;
- bottom DS.W 1 ; bottom: INTEGER;
- right DS.W 1 ; right: INTEGER);
- ORG top ;
- topLeft DS.L Point ; 2: (topLeft: Point;
- botRight DS.L Point ; 3: (botRight: Point)
- ENDR ; END;
-
- BitMap RECORD 0 ; BitMap = RECORD
- baseAddr DS.L 1 ; baseAddr: QDPtr;
- rowBytes DS.W 1 ; rowBytes: INTEGER;
- bounds DS.L Rect ; bounds: Rect
- ENDR ; END;
-
- EventRecord RECORD 0 ; EventRecord = RECORD
- what DS.W 1 ; what: INTEGER;
- message DS.L 1 ; message: LONGINT;
- when DS.L 1 ; when: LONGINT;
- where DS.L Point ; where: Point;
- modifiers DS.W 1 ; modifiers: INTEGER
- ENDR ; END;
-
- EJECT
-
- ***********************
- * QuickDraw's Globals *
- ***********************
-
- * The following data module is used to define the QuickDraw global data area.
- * -----------
-
- QuickDraw RECORD ,DECREMENT
- thePort DS.L 1
- white DS.B 8
- black DS.B 8
- gray DS.B 8
- ltGray DS.B 8
- dkGray DS.B 8
- arrow DS.B cursRec
- screenBits DS.B BitMap
- randSeed DS.L 1
- ORG -grafSize
- ENDR
-
-
- **************************
- * Global Data for Sample *
- **************************
-
- * This is the global data used by Sample. Both these and the QuickDraw data
- * above are referenced through a WITH statetment at the beginning of the procs
- * that use this data. Since the Assembler knows when it is referencing data
- * in a data module (since they must be declared before they are accessed),
- * and since such data can only be accessed based on A5, there is no need to
- * explicitly specify A5 in any code which references the data (unless indexing
- * is used). Thus, in this program we have omitted all A5 references when
- * referencing the data.
-
- GlobalData RECORD
- appleMenuH DS.L 1 ; Handle to the Apple menu
- fileMenuH DS.L 1 ; Handle to the File menu
- editMenuH DS.L 1 ; Handle to the Edit menu
- dragRect DS.L Rect ; Drag limits
- txRect DS.L Rect ; TextEdit's limits
- doneFlag DS.B 1 ; True if Quit command processed
- myEvent DS.L EventRecord ; Current event info
- wRecord DS.B windowSize ; The application window record
- myWindow DS.L 1 ; Ptr to the application window
- whichWindow DS.L 1 ; Current event's window
- textH DS.L 1 ; TextEdit's text handle
- mousePt DS.L Point ; Used to get current mouse point
- iBeamHdl DS.L 1 ; Handle to the iBeam cursor
- ENDR
-
-
- TITLE 'SetupMenus - Set up menus and menu bar'
-
- ******************************************
- * SetUpMenus - Set up menus and menu bar *
- ******************************************
-
- * This is a code module used only during initialization. Note, just as in the
- * Pascal version, this is a distinct code module. Also, since SetUpMenus is
- * only called during initialization, there is no need to keep it loaded. So
- * we will place SetUpMenus in its own segment (called "Initialize") and unload
- * it after SetUpMenus returns.
-
- SEG 'Init' ; This illustrates segmenting!
- PROCEDURE SetUpMenus
-
- BEGIN With=GlobalData
- Call _GetRMenu:L(#appleID),(Pass,appleMenuH); Read Apple menu from rsrc file
- Call _InsertMenu((A7):L, #0) ; Install Apple menu in menu bar
- Call _AddResMenu(, #'DRVR':L) ; Add DA names to Apple menu
-
- Call _GetRMenu:L(#fileID),(Pass,fileMenuH); Read File menu from rsrc file
- Call _InsertMenu(, #0) ; Install File menu in menu bar
-
- Call _GetRMenu:L(#editID),(Pass,editMenuH); Read Edit menu from rsrc file
- Call _InsertMenu(, #0) ; Install Edit menu in menu bar
-
- Call _DrawMenuBar ; Draw the menu bar
- Return ; Exit
- ENDP
-
-
- TITLE 'ShowAboutMeDialog - Display the "About"...'
-
- **********************************************
- * ShowAboutMeDialog - Display the "About"... *
- **********************************************
-
- * This procedure is called from DoCommand when item #1 is selected from the
- * apple menu list. It sets up a dialog box indicating the author and language
- * of this sample program. The box remains until the user clicks the mouse on
- * the continue button.
-
- SEG ; Undo SEG done above
- PROCEDURE ShowAboutMeDialog
-
- VAR savePort: L, \ ; Port at the time of call
- itemType: W, \ ; Returned by _GetDItem (not used)
- itemHdl: L, \ ; Handle to the item
- itemRect: Rect, \ ; Returned by _GetDItem (not used)
- itemHit: W ; Part code
-
- BEGIN Save=A3
- theDialog: EQU A3 ; Dialog pointer
- *
- * Start here: create current grafPort, and allocate space for the dialog box
- *
- Call _GetPort(savePort(FP):A) ; Remember the current grafPort
- Call _GetNewDialog:A(#aboutMeDLOG, NIL, -1:A) ;Create a new dialog
- MOVE.L (A7),theDialog ; theDialog holds ptr to dialog info
- Call _SetPort ; Set the current grafPort
- *
- * Fill in the dialog box with the proper author and language
- *
- Call _GetDItem(theDialog:L, #authorItem, itemType(FP):A, itemHdl(FP):A, \
- itemRect(FP):A); Get dialog's author item info
- Call _SetIText(itemHdl(FP):L, #'Nebur L. Ari':A); Update the author item
-
- Call _GetDItem(theDialog:L, #languageItem, itemType(FP):A, itemHdl(FP):A, \
- itemRect(FP):A); Get dialog's language info
- Call _SetIText(itemHdl(FP):L, #'Assembler':A); Update the language item
- *
- * Wait for user to click the continue button
- *
- REPEAT#
- Call _ModalDialog(NIL, itemHit(FP):A) ; Wait for the click...
- UNTIL#.S itemHit(FP) EQ #okButton
- *
- * User is now satisfied -- let's get out of here!
- *
- Call _CloseDialog(theDialog:L); Close the dialog box
- Call _SetPort(savePort(FP):L) ; Put original grafPort back
- Return
- ENDP
-
-
- TITLE 'DoCommand - Execute a menu command'
-
- ***********************************************************************
- * DoCommand - Execute command specified by the result of a MenuSelect *
- ***********************************************************************
-
- * This is another code module which takes as a parameter the MenuSelect return
- * value. It is next to the top of the stack just before the return address.
-
- PROCEDURE DoCommand;
-
- BEGIN With=GlobalData
- return: EQU A6 ; The return address will be in A6
- mResult: EQU D3 ; mResult will be kept in D3
- theItem: EQU mResult ; LoWord(mResult) is mResult treated as a word
-
- * The following defines some local data known only to this proc.
-
- DATA ; Switch into local data section
- name: DS.B 256 ; Desk accessory name string
- CODE ; Switch back to code section
-
- MOVEA.L (A7)+,return ; Pop return into A6
- MOVE.L (A7)+,mResult ; Pop mResult parameter
-
- MOVE.L mResult,D0 ; Case on menu ID in
- SWAP D0 ; high-order word of mResult
-
- Switch# D0
- Case#.S appleID ; Apple menu processing
- Call _GetItem(appleMenuH:L, theItem, name:A); Get DA name
- IF# theItem EQ #1 THEN.S
- Call ShowAboutMeDialog
- ELSE#.S
- Call _OpenDeskAcc:W(name:A),Pop
- ENDIF#
- Call _SetPort(myWindow:L); Restore app window as grafPort
- Leave#.S ; Exit
-
- Case#.S fileID ; File menu processing
- ST doneFlag ; Set flag to Quit (caller tests)
- Leave#.S ; Exit
-
- Case#.S editID ; Edit menu processing
- MOVE theItem,D1 ; if DA window is the active window
- SUBQ #1,D1 ; SystemEdit requires item adjustment
- Call _SysEdit:B(D1),CC ; Call Desk Mgr to handle editing command
- ; if DA window is the active window
- IF# EQ THEN.S ; App window is active window
- Switch# theItem ; Case on menu item (command) number
- Case#.S cutCommand; Call TextEdit to handle command
- Call _TECut(textH:L)
- Leave#.S
- Case#.S copyCommand
- Call _TECopy(textH:L)
- Leave#.S
- Case#.S pasteCommand
- Call _TEPaste(textH:L)
- Leave#.S
- Case#.S clearCommand
- Call _TEDelete(textH:L)
- EndS# ; of item case
- ENDIF#
- EndS# ; of editID case
-
- Call _HiliteMenu(#0) ; Unhighlight menu item
- JMP (return) ; Exit
- ENDP
-
- TITLE 'Sample - Main Program'
-
- ***********************************************
- * Sample Main Program - Execution starts here *
- ***********************************************
-
- * This is another code module. It is declared as the main code module which
- * means execution will start here.
-
- PROCEDURE Sample,Main=Y
-
- BEGIN With=(QuickDraw,GlobalData) ; Cover our data areas
- *
- * Initialization
- *
- Call _InitGraf(thePort:A) ; Initialize QuickDraw
- Call _InitFonts ; Initialize Font Manager
- MOVE.L #$0000FFFF,D0 ; Discard any previous events
- Call _FlushEvents ; FlushEvents(EventEvent, 0);
- Call _InitWindows ; Initialize Window Manager
- Call _InitMenus ; Initialize Menu Manager
- Call _TEInit ; Initialize TextEdit
- Call _InitDialogs(NIL) ; Initialize Dialog Manager
- Call _InitCursor ; Make cursor an arrow
-
- Call _GetCursor:L(#iBeamCursor),iBeamHdl; Get the iBeam cursor handle to
- ; use in the main ctl loop when
- ; cursor is in the window
-
- Call SetUpMenus ; Set up menus and menu bar
- Call _UnLoadSeg(SetUpMenus:A) ; Unload the SetUpMenus segment since we
- ; will never call it again
-
- WITH screenBits.bounds
- MOVE right,D0 ; Call QuickDraw to set dragging
- SUBQ #4,D0 ; boundaries; ensure at least
- MOVE bottom,D1 ; 4 by 4 pixels will remain visible
- SUBQ #4,D1
- Call _SetRect(dragRect:A, #4, #24, D0, D1)
- ENDWITH
-
- CLR.B doneFlag ; Flag to detect Quit command
-
- Call _GetNewWindow:L(#windowID, wRecord:A, #-1:L),(Pass,myWindow); Put up app window
- Call _SetPort() ; Set current grafPort to this window
- MOVE.L thePort,A0 ; Rectangle for text in window
- MOVE.L portRect+topLeft(A0),txRect.topLeft
- MOVE.L portRect+botRight(A0),txRect.botRight
- Call _InSetRect(txRect:A, #4, #0) ; Bring it in 4 pixels from left/right edges
- Call _TENew:L(txRect:A, txRect:A),textH ; Prepare for receiving text
-
- EJECT
- *
- * Main Event Loop
- *
- REPEAT#
- Call _SystemTask ; Perform periodic actions defined for DAs
-
- Call _FrontWindow:L,D0 ; Get ptr to the front window
- IF# D0 EQ.L myWindow THEN.S ; Front window is my mindow
- Call _GetMouse(mousePt:A); Is mouse pointing in my window ?
- MOVEA.L myWindow,A0
- Call _PtInRect:B(mousePt:L, portRect(A0):A),CC
- IF# NE THEN.S ; Yes, use the iBeam cursor
- MOVE.L iBeamHdl,A0
- MOVE.L (A0),-(A7)
- ELSE#.S ; No, use the arrow cursor
- PEA arrow
- ENDIF#
- Call _SetCursor ; Set cursor to arrow or iBeam
- Call _TEIdle(textH:L) ; Make vertical bar blink
- ENDIF#
-
- Call _GetNextEvent:B(#everyEvent, myEvent:A),CC; ToolBox Event Mgr
- IF# NE THEN
- Switch# myEvent.what,JmpTbl=Y,ChkRng=Y; Case on event type
- Case# mButDwnEvt ; Mouse down event processing
- Call _FindWindow:W(myEvent.where:L, whichWindow:A),D0
- Switch# D0 ; Process according to where
- Case#.S inMenuBar ; Menu bar: process command
- Call _MenuSelect:L(myEvent.where:L)
- Call DoCommand ; DoCommand(MenuSelect(myEvent.where));
- Leave#.S
-
- Case#.S inSysWindow ; Desk accessory window
- Call _SystemClick(myEvent:A, whichWindow:L)
- Leave#.S
-
- Case#.S inDrag ; Title bar
- Call _DragWindow(whichWindow:L, myEvent.where:L, dragRect:A)
- Leave#.S
-
- Case#.S inContent ; Body of application window
- Call _FrontWindow:L,D0 ; Which is in front?
- IF# D0 NE.L whichWindow THEN.S ; Not us!
- Call _SelectWindow(whichWindow:L)
- ELSE#.S ; If we are in front...
- Call _GlobalToLocal(myEvent.where:A)
- MOVE.L myEvent.where,-(A7)
- MOVE myEvent.modifiers,D0
- BTST #shiftKey,D0
- SNE -(A7) ; Indicate if shift key is down
- Call _TEClick(,,textH:L)
- ENDIF#
- EndS#
- Leave#
-
- Case# keyDwnEvt,autoKeyEvt ; Key down and Auto key event processing
- BTST #CmdKey,myEvent.modifiers
- IF# NE THEN.S ; If cmd key down, call Menu Mgr to learn which
- Call _MenuKey:L(myEvent.message+2)
- Call DoCommand ; Process the command key
- ELSE#.S ; If not a command key...
- Call _TEKey(myEvent.message+2, textH:L); ...pass char to TE
- ENDIF#
- Leave#.S
-
- Case# activateEvt ; Activate/deactivate event processing
- MOVE myEvent.modifiers,D0; App window status changed
- BTST #activeFlag,D0 ; Is app window becoming active ?
- IF# NE THEN.S ; Yes
- Call _TEActivate(textH:L) ; Call TE to highlight selection and
- Call _DisableItem(editMenuH:L, #undoCommand); disable UnDo
- ELSE#.S ; App window is becoming inactive
- Call _TEDeactivate(textH:L); Unhighlight selection and
- Call _EnableItem(editMenuH:L, #undoCommand); enable UnDo
- ENDIF#
- Leave#.S
-
- Case# updatEvt ; Update event processing
- Call _BeginUpDate(myEvent.message:L) ; Window needs updating
- MOVEA.L thePort,A3 ; We need thePort^.portRect
- Call _EraseRect(portRect(A3):A) ; Call QD to erase text area
- Call _TEUpdate(portRect(A3):A, textH:L) ; Call TE to update the text
- Call _EndUpDate(myEvent.message:L) ; End update
- ENDS#
- ENDIF#
-
- TST.B doneFlag
- UNTIL# NE
- Return
- END ; of Sample
-